﻿//------------------------------------------------------------------------------
// Written for CP2011 Project @ JCU, 2011
// By Drewan O'Brien
//
// Receives Messages from the client & executes the appropriate action.
//------------------------------------------------------------------------------

using System;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Diagnostics;
using BluSteamServer.Model.TransactionImplementation;

namespace BluSteamServer.Model
{
    public class MessageHandler : IMessageHandler
    {
        #region Fields

        private Socket _socket;
        private ProtocolData _protocolString;
        private TransactionFactory _transactionFactory;

        #endregion

        #region Constructors

        public MessageHandler(Socket socket)
        {
            _socket = socket;
            _transactionFactory = new TransactionFactoryImplementation();

            // create thread to receive messages
            Thread messageThread = new Thread(new ThreadStart(Receive));
            messageThread.IsBackground = true;
            messageThread.Start();
        }

        #endregion

        #region Properties

        public ProtocolData ProtocolString
        {
            get { return _protocolString; }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Receives packets as bytes & converts them to a string.
        /// </summary>
        public void Receive()
        {
            if (_socket == null) return;

            byte[] bytes = new byte[256];

            int numBytes;
            while ((numBytes = _socket.Receive(bytes)) != 0)
            {
                string packet = Encoding.ASCII.GetString(bytes, 0, numBytes);
                Debug.WriteLine(packet);
                this.HandleMessage(packet);
            }

            // if loop exits client has forcibly closed the connection
        }

        public void HandleMessage(string packet)
        {
            if (!packet.StartsWith("$CP2011")) return;

            string[] dataArray = packet.Split('~');

            // create an object from the protocol string to make it easier to handle
            _protocolString = new ProtocolData()
            {
                Identifier = dataArray[0],
                UserName = dataArray[1],
                MessageType = dataArray[2],
                Directive = dataArray[3],
                Password = dataArray[4],
                Recipient = dataArray[5],
                Message = dataArray[6],
                Email = dataArray[7],
                NewPassword = dataArray[8]
            };

            // the clients first login / register message must be treated uniqely
            if (_protocolString.Directive == "LOGIN" || _protocolString.Directive == "REGISTER")
            {
                ConnectionManager.Instance.AddConnection(_protocolString.UserName, _socket);
            }

            // execute the appropriate transaction or command
            if (_protocolString.MessageType == "TRANSACTION")
            {
                Transaction transaction = _transactionFactory.MakeTransaction(_protocolString);
                transaction.Validate();
                transaction.Execute();
            }
            else if (_protocolString.MessageType == "COMMAND")
            {
                Command command = CommandFactory.MakeCommand(_protocolString);
                command.Execute();
            }
        }

        #endregion
    }
}
